﻿//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;

//using System.Threading;
//using System.Net;
//using System.Net.Sockets;

//namespace NetworkingLibrary
//{
//    public class Client
//    {
//        private static int bufferSize = 100000;

//        /// <summary>
//        /// The size of the buffer to use when sending/receiving data. Default value is 100000.
//        /// </summary>
//        public static int BufferSize
//        {
//            get
//            {
//                return bufferSize;
//            }
//            set
//            {
//                if (value >= (Properties.Settings.Default.MaxBufferSize - GlobalMethods.LengthBytesLength))
//                {
//                    throw new InvalidCastException("Value must be less than " + (Properties.Settings.Default.MaxBufferSize - GlobalMethods.LengthBytesLength).ToString());
//                }
//                else
//                {
//                    bufferSize = value;
//                }
//            }
//        }

//        private bool Terminating = false;

//        private Socket TheSocket;
//        private ClientModes TheClientMode;

//        /// <summary>
//        /// Fired when any error occurs.
//        /// </summary>
//        public event ErrorMessageDelegate OnErrorMessage;

//        public delegate void MessageReceivedDelegate(ClientMessageReceivedArgs e);
//        /// <summary>
//        /// Fired when the client receives a message (data).
//        /// </summary>
//        public event MessageReceivedDelegate OnMessageReceived;

//        public delegate void DisconnectDelegate();
//        /// <summary>
//        /// Fired when the client is disconnected.
//        /// </summary>
//        public event DisconnectDelegate OnDisconnected;

//        /// <summary>
//        /// Fired when the client successfully connects to a server.
//        /// </summary>
//        public event ConnectedDelegate OnConnectionAccepted;


//        private AsyncCallback ReceiveCallback;

//        /// <summary>
//        /// Whether the cline tis connected to a server or not.
//        /// </summary>
//        public bool Connected
//        {
//            get
//            {
//                return TheSocket.Connected;
//            }
//        }

//        /// <summary>
//        /// Default constructor.
//        /// </summary>
//        /// <param name="AClientMode">See ClientModes enumerable.</param>
//        /// <param name="OnAMessageReceived">See OnMessageReceived event.</param>
//        public Client(ClientModes AClientMode, MessageReceivedDelegate OnAMessageReceived)
//        {
//            TheClientMode = AClientMode;
//            ReceiveCallback = new AsyncCallback(Receive);
//            OnErrorMessage += new ErrorMessageDelegate(Client_OnErrorMessage);
//            OnMessageReceived += OnAMessageReceived;
//        }

//        private void Client_OnErrorMessage(ErrorMessageEventArgs e)
//        {
//            if (!TheSocket.Connected)
//            {
//                OnDisconnected.Invoke();
//            }
//        }

//        /// <summary>
//        /// Initialises the client and attempts to connect it to the specified IP address and port number.
//        /// </summary>
//        /// <param name="Port">The port number to connect on.</param>
//        /// <param name="TheAddress">The IP address to connect to.</param>
//        /// <returns>Returns true if the client is successfully initailsed and connects to the specified IP address and port number.</returns>
//        public bool Connect(int Port, IPAddress TheAddress)
//        {
//            try
//            {
//                Terminating = false;

//                TheSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//                TheSocket.Connect(TheAddress, Port);
//                OnConnectionAccepted.Invoke();
//                TheSocket.Blocking = false;
//                TheSocket.NoDelay = true;
//                byte[] Buffer = new byte[BufferSize];
//                TheSocket.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, ReceiveCallback, Buffer);

//                return TheSocket.Connected;
//            }
//            catch (Exception e)
//            {
//                OnErrorMessage.Invoke(new ErrorMessageEventArgs(e.Message));
//            }
//            return false;
//        }
//        /// <summary>
//        /// Disconnects the client from the server if it is connected.
//        /// </summary>
//        /// <returns>Rerurns true if the client is disconnected. (Also fires OnDisconnected event)</returns>
//        public bool Disconnect()
//        {
//            try
//            {
//                if (TheSocket != null && TheSocket.Connected)
//                {
//                    switch (TheClientMode)
//                    {
//                        case ClientModes.GameClient:
//                            {
//                                GSSend(new byte[1], true, true);
//                            }
//                            break;
//                        case ClientModes.ManagerClient:
//                            {
//                                MSSend(new byte[1], ManagerServerMessageType.Other, true);
//                            }
//                            break;
//                    }
//                    Terminating = true;
//                    Thread.Sleep(100);
//                    TheSocket.Close(5);
//                    OnDisconnected.Invoke();
//                    return !TheSocket.Connected;
//                }
//                Terminating = true;
//                Thread.Sleep(100);
//                OnDisconnected.Invoke();
//                return true;
//            }
//            catch (Exception e)
//            {
//                OnErrorMessage.Invoke(new ErrorMessageEventArgs(e.Message));
//            }
//            return false;
//        }

//        /// <summary>
//        /// Sends data to the connected server. Use if ClientMode is GameClient.
//        /// </summary>
//        /// <param name="TheBytes">The data to send.</param>
//        /// <param name="ServerOnly">Whether the data is intended for the game server only or all clients of the game server.</param>
//        /// <returns>Returns true if the data is sent. False if the client is not connected or the data fails to send. No error is thrown if the data buffer is longer than the BufferSize.</returns>
//        public bool GSSend(byte[] TheBytes, bool ServerOnly, bool Disconnect)
//        {
//            try
//            {
//                if (!Terminating)
//                {
//                    if (TheSocket != null && TheSocket.Connected)
//                    {
//                        if (TheClientMode == ClientModes.GameClient)
//                        {
//                            GameServerMessageObject TheMO = new GameServerMessageObject(TheBytes, ServerOnly, Disconnect);
//                            TheSocket.Send(GlobalMethods.FormMessage(GlobalMethods.ToBytes(TheMO)));
//                        }
//                    }
//                    else
//                    {
//                        return false;
//                    }
//                }
//                return !Terminating;
//            }
//            catch (Exception e)
//            {
//                OnErrorMessage.Invoke(new ErrorMessageEventArgs(e.Message));
//            }
//            return false;
//        }
//        /// <summary>
//        /// Sends data to the connected server. Use if ClientMode is ManagerClient.
//        /// </summary>
//        /// <param name="TheBytes">The data to send. Data can be null if sending any default type of message.</param>
//        /// <param name="TheMessageType">The type of message to send. Use other if data is not default type.</param>
//        /// <returns>Returns true if the data is sent. False if the client is not connected or the data fails to send. No error is thrown if the data buffer is longer than the BufferSize.</returns>
//        public bool MSSend(byte[] TheBytes, ManagerServerMessageType TheMessageType, bool Disconnect)
//        {
//            try
//            {
//                if (!Terminating)
//                {
//                    if (TheSocket != null && TheSocket.Connected)
//                    {
//                        if (TheClientMode == ClientModes.ManagerClient)
//                        {
//                            ManagerServerMessageObject TheMO = new ManagerServerMessageObject(TheBytes, TheMessageType, Disconnect);
//                            TheSocket.Send(GlobalMethods.FormMessage(GlobalMethods.ToBytes(TheMO)));
//                        }
//                    }
//                    else
//                    {
//                        return false;
//                    }
//                }
//                return !Terminating;
//            }
//            catch (Exception e)
//            {
//                OnErrorMessage.Invoke(new ErrorMessageEventArgs(e.Message));
//            }
//            return false;
//        }

//        private void Receive(IAsyncResult Result)
//        {
//            try
//            {
//                if (!Terminating)
//                {
//                    int BytesRead = TheSocket.EndReceive(Result);
//                    if (BytesRead > 0)
//                    {
//                        byte[] Buffer = new byte[BufferSize];
//                        TheSocket.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, ReceiveCallback, Buffer);
                        
//                        try
//                        {
//                            switch (TheClientMode)
//                            {
//                                case ClientModes.GameClient:
//                                    List<byte[]> AllMessages = GlobalMethods.GetAllMessages((byte[])(Result.AsyncState));
//                                    for (int i = 0; i < AllMessages.Count; i++)
//                                    {
//                                        GameServerMessageObject TheMO = (GameServerMessageObject)(GlobalMethods.FromBytes(AllMessages[i]));
//                                        if (TheMO != null)
//                                        {
//                                            OnMessageReceived.Invoke(new ClientMessageReceivedArgs(TheMO.TheBytes, this));
//                                        }
//                                    }
//                                    break;
//                                case ClientModes.ManagerClient:
//                                    OnMessageReceived.Invoke(new ClientMessageReceivedArgs((byte[])Result.AsyncState, this));
//                                    break;
//                            }
//                        }
//                        catch (Exception e)
//                        {
//                            OnErrorMessage.Invoke(new ErrorMessageEventArgs(e.Message));
//                        }
//                    }
//                    else
//                    {
//                        Disconnect();
//                    }
//                }
//            }
//            catch (Exception e)
//            {
//                OnErrorMessage.Invoke(new ErrorMessageEventArgs(e.Message));
//            }
//        }
//    }

//    public class ClientMessageReceivedArgs : EventArgs
//    {
//        /// <summary>
//        /// The data that was received.
//        /// </summary>
//        public byte[] TheBytes;
//        /// <summary>
//        /// The client that received the message.
//        /// </summary>
//        public Client TheClient;

//        internal ClientMessageReceivedArgs(byte[] ABytes, Client AClient)
//        {
//            TheBytes = ABytes;
//            TheClient = AClient;
//        }
//    }

//}
